package test.demo;

import com.alibaba.fastjson.JSON;
import lombok.*;
import tech.waterism.modelbase.PredictBase;
import tech.waterism.modelbase.PredictResult;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.DoubleStream;

/**
 * 滞后演算-河道演进
 *
 * @author 初京刚
 * @version 1.0
 * @date 2023-6-23
 */
public class LAG extends PredictBase {

    /**
     * 流域基流
     */
    @Setter
    @Getter
    private double Qbasic;

    /**
     * 初始总基流
     */
    private double[] QSInitial;

    /**
     * 径流消退系数
     */
    private double CS;

    /**
     * 滞时（h）
     */
    private double L;

    /**
     * 降水时间
     */
    @Setter
    @Getter
    private Date[] floodTm;

    /**
     * 降水序列长度
     */
    private Integer floodRainRange;

    /**
     * 降水时段长
     */
    @Setter
    @Getter
    private double timeInterval;

    /**
     * 模拟总产流
     */
    @Getter
    private double[] runoffSim;

    /**
     * 上游断面流量过程
     */
    private double[] Q;

    public LAG(Map<String, String> data) {
        super();
//        Qbasic = Double.parseDouble(data.get("Qbasic"));
//        QSInitial = JSON.parseObject(data.get("QSIG"), double[].class);
//        floodTm = JSON.parseObject(data.get("dt"), Date[].class);               // input[i].data.dt
//        runoffSim = JSON.parseObject(data.get("runoffSim"), double[].class);    // inout[i].data.runoffSim
        CS = Double.parseDouble(data.get("K"));
        L = Double.parseDouble(data.get("T"));
//        timeInterval = Double.parseDouble(data.get("clen"));                    // index.clen
//        floodRainRange = runoffSim.length;
        // from MSK
        Q = JSON.parseObject(data.get("q"), double[].class);      // input[i].data.q
        // 在数组前插入第 0 个元素,值为 0
        Q = DoubleStream.concat(DoubleStream.of(0.0), Arrays.stream(Q)).toArray();
    }

    public void setRunoffSim(double[] paramRunoffSim) {
        this.runoffSim = paramRunoffSim;
        floodRainRange = runoffSim.length;
    }

    /**
     * 模型计算
     */
    public Map<String, double[]> LAGmodel() {

        //滞后演算
        double[] QSim = Lag();

        Map<String, double[]> simulationResult = new HashMap<>();

        simulationResult.put("runoffSim", runoffSim);
        simulationResult.put("QSim", QSim);
        return simulationResult;
    }

    /**
     * 滞后演算
     */
    private double[] Lag() {

        // 汇流 from LAG.dll
        double[] ssQ = new double[Q.length];

        for (int i = 1; i < ssQ.length; i++) {
            ssQ[i] = Q[i] * CS;
        }

        double a = 0;
        for (int i = 1; i < ssQ.length; i++) {
            a += Q[i];
            int j = i + (int) L;
            if (j < ssQ.length) {
                ssQ[j] = a * CS;
            }
            a *= (1 - CS);
        }

        return ssQ;
    }

    @Override
    public void init() {

    }

    @Override
    public PredictResult predict() {
        PredictResult result = new PredictResult();
        Map<String, double[]> map = LAGmodel();
        double[] qSimWithoutFirstElement = Arrays.stream(map.get("QSim"))
                .skip(1) // 去掉第一个元素
                .toArray();
        //河道演进结果
        result.setQSim(qSimWithoutFirstElement);
        return result;
    }

    public static void main(String[] args) {
        String a = "{\"K\":\"0.8\",\"T\":\"2\",\"dt\":\"[\\\"2024-03-23 08:00:00\\\",\\\"2024-03-23 09:00:00\\\",\\\"2024-03-23 10:00:00\\\",\\\"2024-03-23 11:00:00\\\",\\\"2024-03-23 12:00:00\\\",\\\"2024-03-23 13:00:00\\\",\\\"2024-03-23 14:00:00\\\",\\\"2024-03-23 15:00:00\\\",\\\"2024-03-23 16:00:00\\\",\\\"2024-03-23 17:00:00\\\",\\\"2024-03-23 18:00:00\\\",\\\"2024-03-23 19:00:00\\\",\\\"2024-03-23 20:00:00\\\",\\\"2024-03-23 21:00:00\\\",\\\"2024-03-23 22:00:00\\\",\\\"2024-03-23 23:00:00\\\",\\\"2024-03-24 00:00:00\\\"]\",\"q\":\"[22.41,22.41,22.41,143.60,92.34,62.76,45.73,844.17,924.37,812.74,655.58,530.42,441.97,443.80,383.78,236.61,22.41]\",\"runoffSim\":\"[]\",\"QSIG\":\"[0.0, 0.0]\",\"Qbasic\":\"0.0\",\"start\":\"\\\"2024-03-23 08:00:00\\\"\",\"clen\":\"1\"}";
        System.out.println(a);
        Map data = JSON.parseObject(a, Map.class);
        LAG model = new LAG(data);
        PredictResult result = model.predict();
        System.out.println(result);
    }
}